package com.billdowney.util.zxing;

import java.awt.image.BufferedImage;
import java.io.File;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

/**
 * @ClassName: CreateQRCode
 * @Description: 创建二维码工具类
 * @author 超级小富翁 - BillDowney
 * @date 2018年1月6日 下午6:19:17
 */
public class CreateQRCode {

	// 二维码默认大小
	private final static int DEFAULT_SIZE = 1000;
	// 二维码距离边界的距离
	private final static int DEFAULT_MARGIN = 1;
	// 默认生成二维码的文件格式
	public final static String DEFAULT_FILE_FORMAT = "png";
	// 生成二维码的默认路径，相对于项目路径
	public final static String DEFAULT_FILE_PATH = "temp";
	// 生成二维码文件的默认文件名
	public final static String DEFAULT_FILE_NAME = "QRcode";

	/**
	 * @Function: createQRCodeByBufferedImage
	 * @Description: 传入需要生成二维码的内容，默认长度1000px
	 *
	 * @param content 二维码展示的内容
	 * @return 含有二维码的BufferedImage对象
	 *
	 * @author: 超级小富翁 - BillDowney
	 * @date: 2018年1月6日 下午4:39:51
	 */
	public static BufferedImage createQRCodeByBufferedImage(String content) {
		return MatrixToImageWriter.toBufferedImage(getBitMatrix(content, 0));
	}

	/**
	 * @Function: createQRCodeByBufferedImage
	 * @Description: 传入需要生成二维码的内容和大小，单位px
	 *
	 * @param content 二维码展示的内容
	 * @param size    二维码大小，单位px
	 * @return 含有二维码的BufferedImage对象
	 *
	 * @author: 超级小富翁 - BillDowney
	 * @date: 2018年1月6日 下午5:00:51
	 */
	public static BufferedImage createQRCodeByBufferedImage(String content, int size) {
		return MatrixToImageWriter.toBufferedImage(getBitMatrix(content, size));
	}

	/**
	 * @Function: createQRCodeByFile
	 * @Description: 通过传入内容在默认的用户目录生成二维码文件，如果存在Desktop则在Desktop里生成
	 *
	 * @param content 二维码展示的内容
	 * @return 二维码文件路径
	 *
	 * @author: 超级小富翁 - BillDowney
	 * @date: 2018年1月6日 下午5:45:16
	 */
	public static String createQRCodeByFile(String content) {
		String filePath = System.getProperty("user.home") + "/";
		return createQRCodeByFile(content, filePath);
	}

	/**
	 * @Function: createQRCodeByFile
	 * @Description: 传入内容和绝对路径来保存生成的二维码文件
	 *
	 * @param content 二维码展示的内容
	 * @param path    文件绝对路径
	 * @return 文件所在的位置
	 *
	 * @author: 超级小富翁 - BillDowney
	 * @date: 2018年1月6日 下午6:00:54
	 */
	public static String createQRCodeByFile(String content, String path) {
		String fileName = DEFAULT_FILE_NAME + "_" + System.currentTimeMillis() + "_" + new Random().nextInt(100) + "."
				+ DEFAULT_FILE_FORMAT;
		return createQRCodeByFile(content, path, fileName);
	}

	public static String createQRCodeByFile(String content, String path, String fileName) {
		String filePath = path;
		if (!(filePath.endsWith(File.separator) || filePath.endsWith("/"))) {// 结尾是否以"/"结束
			filePath = filePath + File.separator;
		}
		createDir(path);
		filePath = filePath + fileName + "." + DEFAULT_FILE_FORMAT;
		// 生成二维码
		try {
			BitMatrix bitMatrix = getBitMatrix(content, 0);
			Path file = new File(filePath).toPath();
			MatrixToImageWriter.writeToPath(bitMatrix, DEFAULT_FILE_FORMAT, file);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return filePath;
	}

	/**
	 * @Function: getBitMatrix
	 * @Description: 更具传入的内容和大小生成相应的BitMatrix
	 *
	 * @param content 内容
	 * @param size    大小
	 * @return BitMatrix对象
	 *
	 * @author: 超级小富翁 - BillDowney
	 * @date: 2018年1月6日 下午4:56:39
	 */
	private static BitMatrix getBitMatrix(String content, int size) {
		BitMatrix bitMatrix = null;
		if (size <= 0) {
			size = DEFAULT_SIZE;
		}
		// 定义二维码参数
		Map<EncodeHintType, Object> hints = new HashMap<>();
		hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
		hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
		hints.put(EncodeHintType.MARGIN, DEFAULT_MARGIN);
		// 生成二维码
		try {
			bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, size, size, hints);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return bitMatrix;
	}

	/**
	 * 创建目录
	 * 
	 * @params destDirName 目录路径
	 * @return 是否成功
	 * @anthor billdonwey
	 */
	private static boolean createDir(String destDirName) {
		File dir = new File(destDirName);
		if (dir.exists()) {// 判断目录是否存在
			return false;
		}
		if (!destDirName.endsWith(File.separator)) {// 结尾是否以"/"结束
			destDirName = destDirName + File.separator;
		}
		if (dir.mkdirs()) {// 创建目标目录
			return true;
		} else {
			return false;
		}
	}
}
